package com.yonyou.pmclouds.workflow.service.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.entity.PageObject;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.basecom.util.CommonProgramConsts;
import com.yonyou.pmclouds.billtype.entity.BillTypeVO;
import com.yonyou.pmclouds.billtype.rmiitf.BillTypeQuery;
import com.yonyou.pmclouds.workflow.entity.ProcessDataSynVO;
import com.yonyou.pmclouds.workflow.entity.ProcessDefinitionVO;
import com.yonyou.pmclouds.workflow.mapper.ProcessDefinitionMapper;
import com.yonyou.pmclouds.workflow.processor.DefinitionCheckRule;
import com.yonyou.pmclouds.workflow.processor.ProcessStatusCheck;
import com.yonyou.pmclouds.workflow.service.ProcessModelDefinitionService;
import com.yonyou.pmclouds.workflow.service.rmiitf.BaseManagerService;
import com.yonyou.pmclouds.workflow.service.rmiitf.ProcessDefinitionService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * bpm流程操作基本服务
 */
@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = ProcessDefinitionService.class, timeout = 7000)
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {

    private final ProcessDefinitionMapper definitionMapper;

    private final ProcessModelDefinitionService modelDefinitionService;

    private final BaseManagerService baseManagerService;

    private final BillTypeQuery billTypeQuery;

    @Autowired
    public ProcessDefinitionServiceImpl(ProcessDefinitionMapper definitionMapper,
                                        ProcessModelDefinitionService modelDefinitionService,
                                        BaseManagerService baseManagerService, BillTypeQuery billTypeQuery) {
        this.definitionMapper = definitionMapper;
        this.modelDefinitionService = modelDefinitionService;
        this.baseManagerService = baseManagerService;
        this.billTypeQuery = billTypeQuery;
    }

    @Override
    public ProcessDefinitionVO insertProcessDefinitionModel(ProcessDefinitionVO definitionVO) throws BusinessException {
        BillTypeVO billTypeVO = billTypeQuery.queryBillByType(definitionVO.getBillType(), BillTypeVO.DATA_USAGE_APPROVAL);

        // 在云审批中创建流程模型
        definitionVO = modelDefinitionService.insertProcessDefinition(definitionVO);

        if(definitionVO != null) {
            SingleInsertBpTemplate<ProcessDefinitionVO> bp = new SingleInsertBpTemplate<>(definitionMapper);
            bp.addBeforeProcessor(new DefinitionCheckRule(definitionMapper));
            definitionVO = bp.insert(definitionVO);

            // 同步表单和表单字段
            baseManagerService.addFormDataSyn(definitionVO.getProcessId(), billTypeVO,
                    definitionVO.getUserId(), definitionVO.getPkTenant());
        }
        return definitionVO;
    }

    @Override
    public ProcessDefinitionVO updateProcessStatus(ProcessDefinitionVO definitionVO) throws BusinessException {
        String[] updateFields = new String[]{CommonFieldConst.MODIFIER, CommonFieldConst.MODIFYTIME,
                ProcessDefinitionVO.PROCESS_STATUS};
        SingleUpdateBpTemplate<ProcessDefinitionVO> bpTemplate = new SingleUpdateBpTemplate<>(definitionMapper, updateFields);
        bpTemplate.addBeforeProcessor(new ProcessStatusCheck(definitionMapper));
        return bpTemplate.update(definitionVO);
    }

    @Override
    public PageObject<ProcessDefinitionVO> queryProcessDefinition(String tenantId, String billType, int start,
                                                                  int offset, String pkOrg) throws BusinessException {
        if (offset > CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE) {
            offset = CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE;
        }
        if (offset < CommonProgramConsts.DEFAULT_MIN_QUERY_SIZE) {
            offset = CommonProgramConsts.DEFAULT_MIN_QUERY_SIZE;
        }
        int count = definitionMapper.countDefinitionByTenantId(tenantId, billType, pkOrg);
        ProcessDefinitionVO[] definitionVOS = definitionMapper.queryDefinitionByTenantId(tenantId, billType, start, offset, pkOrg);
        return new PageObject<>(definitionVOS, count, start);
    }

    @Override
    public void deleteDefinition(ProcessDefinitionVO definitionVO) throws BusinessException {
        // 删除云审批表单和表单字段
        baseManagerService.deleteFormData(definitionVO.getProcessId(), definitionVO.getUserId(), definitionVO.getPkTenant());

        boolean deleteResult = modelDefinitionService.deleteDefinition(definitionVO);

        if(deleteResult) {
            ProcessDefinitionVO tempDefinitionVO = new ProcessDefinitionVO();
            tempDefinitionVO.setPkProcessDefinition(definitionVO.getPkProcessDefinition());
            tempDefinitionVO.setChangeFlag(definitionVO.getChangeFlag());
            SingleDeleteBpTemplate<ProcessDefinitionVO> deleteBpTemplate = new SingleDeleteBpTemplate<>(definitionMapper);
            deleteBpTemplate.delete(tempDefinitionVO);
        }
    }

    @Override
    public ProcessDefinitionVO updateDefinition(ProcessDefinitionVO definitionVO) throws BusinessException {
        // 更新表单和表单字段
        BillTypeVO billTypeVO = billTypeQuery.queryBillByType(definitionVO.getBillType(), BillTypeVO.DATA_USAGE_APPROVAL);
        baseManagerService.addFormDataSyn(definitionVO.getProcessId(), billTypeVO,
                definitionVO.getUserId(), definitionVO.getPkTenant());

        modelDefinitionService.updateDefinition(definitionVO);

        String[] updateFields = new String[]{CommonFieldConst.MODIFIER, CommonFieldConst.MODIFYTIME,
                ProcessDefinitionVO.PROCESS_NAME, ProcessDefinitionVO.PK_ORG,ProcessDefinitionVO.IS_ASSIGN_FILTER};
        SingleUpdateBpTemplate<ProcessDefinitionVO> bpTemplate = new SingleUpdateBpTemplate<>(definitionMapper, updateFields);
        return bpTemplate.update(definitionVO);
    }

    @Override
    public String getDesignerUrl(){
        return modelDefinitionService.getDesignerUrl();
    }

    @Override
    public BillTypeVO[] queryBillType(String tenantId) throws BusinessException {
        return billTypeQuery.queryBillTypeByTenantId(tenantId);
    }

    @Override
    public ProcessDataSynVO checkIsBaseDataSyn(String tenantId) throws BusinessException {
        return baseManagerService.checkIsBaseDataSyn(tenantId);
    }
}
